#include "jfiledevice_p.h"

namespace JXQ
{

inline bool JFileDevicePrivate::isExist(const JString &name)
{
#if 0
	return access(name.c_str(), 0) == 0;
#else
	FILE* fp = nullptr;

#ifdef _MSC_VER
	J_UNUSED(fopen_s(&fp, name.c_str(), "r"));
#else
	fp = fopen(name.c_str(), "r");
#endif

	if( fp == nullptr )
		return false;
	fclose(fp);
	return true;
#endif
}

bool JFileDevicePrivate::openCheck(OpenMode mode) const
{
	if( m_isOpen )
		return true;

	else if( (mode & JAbstractIO::NotOpen) )
	{
		if( mode & JAbstractIO::DoNotCreate )
			return false;
		else if( isExist(m_name) )
			return false;
	}
	return true;
}

/*--------------------------------------------------------------------------*/

JFileDevice::JFileDevice() :
	JAbstractIO(new JFileDevicePrivate(this))
{

}

JFileDevice::JFileDevice(const JString &name) :
	JFileDevice()
{
	d_func()->m_name = name;
}

JFileDevice::~JFileDevice()
{

}

JString JFileDevice::readLine()
{
	return "";
}

int64_t JFileDevice::ioctl(unsigned int cmd, void *arg)
{
	J_UNUSED(cmd);
	J_UNUSED(arg);
	return 0;
}

void JFileDevice::flush()
{

}

int64_t JFileDevice::bytesAvailable() const
{
	return 0;
}

int64_t JFileDevice::seek(SeekWhence whence, int64_t offset)
{
	J_UNUSED(whence);
	J_UNUSED(offset);
	return 0;
}

int64_t JFileDevice::tell() const
{
	return 0;
}

int64_t JFileDevice::size() const
{
	return 0;
}

void JFileDevice::setName(const JString &name)
{
	if( not d_ptr->m_isOpen )
	{
		J_MUTEX_LOCKER(d_func()->m_nameMutex);
		d_func()->m_name = name;
	}
}

JString JFileDevice::name() const
{
	return d_func()->m_name;
}

void JFileDevice::setAutoCloseHandle(bool enable)
{
	J_UNUSED(enable);
}

bool JFileDevice::autoCloseHandle() const
{
	return true;
}

bool JFileDevice::isExist() const
{
	return JFileDevicePrivate::isExist(d_func()->m_name);
}

bool JFileDevice::isExist(const JString &name)
{
	return JFileDevicePrivate::isExist(name);
}

JHandle JFileDevice::handle() const
{
	return d_func()->m_handle;
}

FILE *JFileDevice::stdStreamPointer() const
{
	return d_func()->toFILE();
}

int64_t JFileDevice::virtualRead(int64_t bufSize, void *buffer)
{
	J_UNUSED(buffer);
	J_UNUSED(bufSize);

	setErrno(0);

	if( d_ptr->check(ReadOnly) == false )
		return -1;

	return 0;
}

int64_t JFileDevice::virtualWrite(int64_t bufSize, const void *buffer)
{
	J_UNUSED(buffer);
	J_UNUSED(bufSize);

	setErrno(0);

	if( d_ptr->check(WriteOnly) == false )
		return -1;

	return 0;
}

JDebug &operator<<(JDebug &d, const JFileDevice *fileDev)
{
	auto c = d.channel();
	if( c == d.StdOut )
		std::cout << "JFileDevice(\"" << fileDev->d_func()->m_name.c_str() << "\")";
	else if( c == d.StdErr )
		std::cerr << "JFileDevice(\"" << fileDev->d_func()->m_name.c_str() << "\")";
	else if( c == d.Log )
		std::clog << "JFileDevice(\"" << fileDev->d_func()->m_name.c_str() << "\")";
	return d;
}

JDebug &operator<<(JDebug &&d, const JFileDevice *fileDev)
{
	return d << fileDev;
}

JDebug &operator<<(JDebug &d, const JFileDevice &fileDev)
{
	return d << &fileDev;
}

JDebug &operator<<(JDebug &&d, const JFileDevice &fileDev)
{
	return d << &fileDev;
}

} // namespace JXQ
